package agents;

import interfaces.CarStatus;
import interfaces.Settings;

import java.util.Random;
import java.util.GregorianCalendar;


import model.agent.Agent;
import message.CPMessage;

public class CarAgent extends Agent {
	
	private static final Random RANDOM = new Random(System.currentTimeMillis());
	private static final String STATUS = "STATUS";
	
	private static final String EntryTime = "EntryTime";
	private static final String LeavingTime = "LeavingTime";
	
	private static final String IsFullyCharged = "IsFullyCharged";
	private static final String MaxPower = "MaxPower";
	private static final String Power = "Power"; 
	
	private static final String ParkingDuration = "ParkingDuration";
	private static final String EnergyRequirement = "EnergyRequirement";
	private static final String PriceRequirement = "PriceRequirement";
	private static final String RandomToLeave = "RandomToLeave";
	
	/**
	 * Constructor
	 */
	public CarAgent(String id) {
		super(id);
		initText(TYPE, "Car");
		initInt(STATUS, CarStatus.INITIALIZE);
		
		initTime(EntryTime, new GregorianCalendar());
		initTime(LeavingTime, new GregorianCalendar());
		
		initInt(MaxPower, Settings.MAX_POWER);
		initInt(Power, RANDOM.nextInt(Settings.MAX_POWER));
		initBool(IsFullyCharged, false);
		
		initInt(ParkingDuration, RANDOM.nextInt(Settings.PARKING_DURATION));
		initInt(EnergyRequirement, Settings.ENERGY_REQUIREMENT);
		initInt(PriceRequirement, Settings.PRICE_REQUIREMENT);
		
		initNumber(RandomToLeave, Settings.RANDOM_TO_LEAVE);
	}
	
	@Override
	public void act() throws Exception {
		switch (getInt(STATUS)) {
			case CarStatus.INITIALIZE:
				requestToPark();
				break;
			case CarStatus.REQUEST_TO_PARK:
				while (messages().hasMessage()) {
					CPMessage receiveMessage = (CPMessage)messages().getMessage();
					if (receiveMessage.getStatus() == CarStatus.ENTER) {
						enter();
					}
				}
				break;
			case CarStatus.ENTER:
				while (messages().hasMessage()) {
					CPMessage receiveMessage = (CPMessage)messages().getMessage();
					charging(1);
					if (getInt(Power) >= getInt(MaxPower)) {
						isFullyCharge();
					}
				}
				
				// RANDOM TO LEAVE
				double temp = RANDOM.nextDouble();
				if (temp < getNumber(RandomToLeave)) {
					System.out.println(getID()+" Random to Leave.");
					requestToLeave();
					setTimeNow(LeavingTime);
					break;
				}
				// TIME IS UP
				if (new GregorianCalendar().after(getTime(LeavingTime))) {
					requestToLeave();
					break;
				}	
			case CarStatus.REQUEST_TO_LEAVE:
				while (messages().hasMessage()) {
					CPMessage receiveMessage = (CPMessage)messages().getMessage();
					if (receiveMessage.getStatus() == CarStatus.LEAVE) {
						leave();
					}
				}
		}
	}
	
	// STATUS
	
	public void requestToPark() {
		System.out.println(getID() + " requestToPark." + " ParkingDuration is " + getInt(ParkingDuration));
		randLeavingTime();
		setInt(STATUS, CarStatus.REQUEST_TO_PARK);
		CPMessage deliverMessage = new CPMessage(getID(), getInt(STATUS));
		messages().sendMessage("CarParkAgent", deliverMessage);
	}
	
	public void enter() {
		System.out.println(getID() + " enter to the parking lot." + " entryTime is " + getTime(EntryTime).get(GregorianCalendar.MINUTE));
		setTimeNow(EntryTime);
		setInt(STATUS, CarStatus.ENTER);
	}
	
	public void requestToLeave() {
		System.out.println(getID() + " requestToLeave");
		setInt(STATUS, CarStatus.REQUEST_TO_LEAVE);
		CPMessage deliverMessage = new CPMessage(getID(), CarStatus.REQUEST_TO_LEAVE);
		messages().sendMessage(Settings.CAR_PARK_AGENT, deliverMessage);
	}
	
	public void leave() {
		System.out.println(getID() + " leave to the parking lot." + " leavingTime is " + getTime(LeavingTime).get(GregorianCalendar.MINUTE));
		delete();
	}
	
	public void waiting() {
	}
	
	// STAGE
	public void isFullyCharge() {
		setBool(IsFullyCharged, true);
		CPMessage deliverMessage = new CPMessage(getID(), getBool(IsFullyCharged));
		messages().sendMessage(Settings.CAR_PARK_AGENT, deliverMessage);
	}
	
	// METHOD
	public void randLeavingTime() {
		GregorianCalendar leavingTime = getTime(EntryTime);
		leavingTime.set(leavingTime.MINUTE, leavingTime.get(GregorianCalendar.MINUTE)+getInt(ParkingDuration));
		setTime(LeavingTime, leavingTime);
	}
	
	public void charging(int powerSupply) {
		setInt(Power, getInt(Power)+powerSupply);
		System.out.println(getID() + " Power is " + getInt(Power));
	}
	
	
}
